<?php

namespace Biz\tools;

use Doraemon\tools\Youzan;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Psr\Http\Message\RequestInterface;

class RealUrl
{
    const URL_REGEX = '#\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#iS';
    const DEFAULE_CONFIG = [
        RequestOptions::TIMEOUT => 10
    ];

    const REDIR_MAX_TIME = 5;

    const URL_HIT_CODE = -1;

    const PROTOCOL = 'https://';

    const M_TB_CN_HOST = 'm.tb.cn';
    const S_CLICK_TAOBAO_HOST = 's.click.taobao.com';
    const S_CLICK_TMALL_HOST = 's.click.tmall.com';
    const I_CLICK_TAOBAO_HOST = 'i.click.taobao.com';
    const ULAND_TAOBAO_HOST = 'uland.taobao.com';

    const ITEM_TAOBAO_HOST = 'item.taobao.com';
    const DETAIL_TMALL_HOST = 'detail.tmall.com';

    const ITEM_JD_HOST = 'item.jd.com';

    const URL_TYPE_TAOBAO = 1;
    const URL_TYPE_TMALL = 2;
    const URL_TYPE_JD = 3;
    const URL_TYPE_YOUZAN = 6;
    const URL_TYPE_XIAOEPINPIN = 8;
    const URL_TYPE_AMAZON = 9;
    const URL_TYPE_XIAOMIYOUPIN = 10;
    const URL_TYPE_SAMSUNGESHOP = 12;

    const HOST_MAP = [
        '.taobao.com' => self::URL_TYPE_TAOBAO,
        '.tmall.com' => self::URL_TYPE_TMALL,
        '.tmall.hk' => self::URL_TYPE_TMALL,
        '.jd.com' => self::URL_TYPE_JD,
        '.jd.hk' => self::URL_TYPE_JD,
        '.youzan.com' => self::URL_TYPE_YOUZAN,
        'ares.xepp.qq.com' => self::URL_TYPE_XIAOEPINPIN,
        'www.amazon.cn' => self::URL_TYPE_AMAZON,
        'xiaomiyoupin.com' => self::URL_TYPE_XIAOMIYOUPIN,
        'samsungeshop.com.cn' => self::URL_TYPE_SAMSUNGESHOP,
        'shop.samsung.com.cn' => self::URL_TYPE_SAMSUNGESHOP,
    ];

    const SHOP_TAOBAO_HOST = 'https://shop%s.taobao.com';
    const SHOP_JD_HOST = 'https://mall.jd.com/index-%s.html';

    // 京东国际
    // 京东m端
    // 京东标准链接

    public static function getRealUrl($url, $count = 0)
    {
        $count++;
        if ($count >= self::REDIR_MAX_TIME) {
            return $url;
        }
        $urlArr = parse_url($url);
        $urlHost = $urlArr['host'];
        switch ($urlHost) {
            case self::M_TB_CN_HOST:
                $redirUrl = self::getMTbCnUrl($url);
                return self::getRealUrl($redirUrl, $count);
                break;
            case self::S_CLICK_TAOBAO_HOST:
            case self::I_CLICK_TAOBAO_HOST:
                $redirUrl = self::getClickUrl($url);
                return self::getRealUrl($redirUrl, $count);
                break;
            case self::S_CLICK_TMALL_HOST:
                $urlQuery = $urlArr['query'];
                $params = [];
                foreach (explode('&', $urlQuery) as $couple) {
                    list ($key, $val) = explode('=', $couple);
                    $params[$key] = $val;
                }
                if (isset($params['tar'])) {
                    $tarUrl = urldecode($params['tar']);
                    return self::getRealUrl($tarUrl, $count);
                } else {
                    return false;
                }
                break;
            case self::ULAND_TAOBAO_HOST:
                $redirUrl = self::getUlandUrl($url);
                return self::getRealUrl($redirUrl, $count);
                break;
            default:
                return self::getRedirectUrl($url);
                break;
        }
    }

    public static function regexUrl($content)
    {
        if (preg_match(self::URL_REGEX, $content, $match)) {
            return $match[1];
        } else {
            return false;
        }
    }

    public static function getItemId($url, $urlType = NUll)
    {
        if (is_null($urlType)) {
            $urlType = self::getUrlType($url);
        }
        switch ($urlType) {
            case self::URL_TYPE_TAOBAO:
            case self::URL_TYPE_TMALL:
                $urlQuery = parse_url($url, PHP_URL_QUERY);
                parse_str($urlQuery, $urlParams);
                if (isset($urlParams['id'])) {
                    return $urlParams['id'];
                } else {
                    return false;
                }
                break;
            case self::URL_TYPE_JD:
                $urlPath = parse_url($url, PHP_URL_PATH);
                $itemId = pathinfo($urlPath, PATHINFO_FILENAME);
                if (is_numeric($itemId)) {
                    return $itemId;
                } else {
                    return false;
                }
                break;
        }
    }

    public static function getUrlType($url)
    {
        foreach (self::HOST_MAP as $value => $type) {
            if (strpos($url, $value) !== false) {
                return $type;
            }
        }
        return false;
    }

    public static function getRedirectUrl($url)
    {
        $format = self::formatUrl($url);
        if ($format) {
            return $format;
        }
        try {
            $client = new Client(self::DEFAULE_CONFIG);
            $client->head($url, [
                'allow_redirects' => [
                    'on_redirect' => function (RequestInterface $request, $response, $uri
                    ) {
                        $format = self::formatUrl($request->getUri());
                        if ($format) {
                            throw new \Exception($format, self::URL_HIT_CODE);
                        }
                    }
                ]
            ]);
            return false;
        } catch (\Exception $e) {
            if ($e->getCode() == self::URL_HIT_CODE) {
                return $e->getMessage();
            } else {
                return false;
            }
        }
    }

    private static function getUlandUrl($url)
    {
        $urlQuery = parse_url($url, PHP_URL_QUERY);
        parse_str($urlQuery, $urlParams);
        $client = new Client(self::DEFAULE_CONFIG);
        try {
            $response = $client->get('http://47.106.188.80/api/tao/v1.0/goods/coupon', [
                'query' => [
                    'type' => isset($urlParams['pid']) ? 1 : 0,
                    'e' => $urlParams['e']
                ]
            ]);
            $content = $response->getBody()->getContents();
            $resultData = json_decode($content, true);
            if (isset($resultData['data']['goods_id'])) {
                return self::PROTOCOL . self::ITEM_TAOBAO_HOST . '/item.html?id=' . $resultData['data']['goods_id'];
            } else {
                return false;
            }
        } catch (\Exception $e) {
            return false;
        }
    }

    private static function getClickUrl($url)
    {
        $client = new Client(self::DEFAULE_CONFIG);
        try {
            $response = $client->get($url);
            $content = $response->getBody()->getContents();
            preg_match('/var real_jump_address = \'(.*)\'/', $content, $matches);
            if ($matches && isset($matches[1])) {
                $jumpUrl = html_entity_decode($matches[1]);
                $response = $client->get($jumpUrl, [
                    'headers' => [
                        'Referer' => $url
                    ],
                    'allow_redirects' => false
                ]);
                if ($response->getStatusCode() == '302') {
                    return $response->getHeaderLine('Location');
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } catch (\Exception $e) {
            return false;
        }
    }

    private static function getMTbCnUrl($url)
    {
        $client = new Client(self::DEFAULE_CONFIG);
        try {
            $response = $client->get($url);
            $content = $response->getBody()->getContents();
            preg_match('/var url = \'(.*)\'/', $content, $matches);
            if ($matches && isset($matches[1])) {
                return $matches[1];
            } else {
                return false;
            }
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 域名格式化
     * https://confluence.haohaozhu.me/pages/viewpage.action?pageId=8192029
     * @param $url
     * @return bool|string
     */
    public static function formatUrl($url)
    {
        $urlHost = parse_url($url, PHP_URL_HOST);
        switch ($urlHost) {
            case 'item.jd.com':
            case 'item.m.jd.com':
            case 'item.jd.hk':
            case 'mitem.jd.hk':
                return self::formatJdUrl($url);
                break;
            case 'detail.m.tmall.com':
            case 'detail.tmall.com':
            case 'item.tmall.hk':
            case 'chaoshi.detail.tmall.com':
                return self::formatTaoBaoUrl($url, self::DETAIL_TMALL_HOST);
                break;
            case 'h5.m.taobao.com':
            case 'm.intl.taobao.com':
                if (!self::checkTaoBaoUrl($url)) {
                    return false;
                }
            case 'detail.tmall.hk':
            case 'item.taobao.com':
            case 'new.m.taobao.com':
                return self::formatTaoBaoUrl($url);
                break;
            case 'detail.ju.taobao.com':
                return self::formatTaoBaoUrl($url, self::DETAIL_TMALL_HOST, 'item_id');
                break;
            default:
                if (strpos($urlHost, 'youzan.com')) {
                    return self::formatYouZanUrl($url, $urlHost);
                }
                return false;
        }
    }

    private static function formatJdUrl($url)
    {
        $urlPath = parse_url($url, PHP_URL_PATH);
        $itemId = pathinfo($urlPath, PATHINFO_FILENAME);
        if (is_numeric($itemId)) {
            return self::PROTOCOL . self::ITEM_JD_HOST . '/' . $itemId . '.html';
        } else {
            return false;
        }
    }

    private static function checkTaoBaoUrl($url)
    {
        $urlPath = parse_url($url, PHP_URL_PATH);
        $pathFileName = pathinfo($urlPath, PATHINFO_FILENAME);
        if ($pathFileName == 'detail') {
            return true;
        } else {
            return false;
        }
    }

    private static function formatTaoBaoUrl($url, $host = self::ITEM_TAOBAO_HOST, $param = 'id')
    {
        $urlQuery = parse_url($url, PHP_URL_QUERY);
        parse_str($urlQuery, $urlParams);
        if (isset($urlParams[$param])) {
            return self::PROTOCOL . $host . '/item.html?id=' . $urlParams[$param];
        } else {
            return false;
        }
    }

    private static function formatYouZanUrl($url, $host, $param = 'alias')
    {
        $urlQuery = parse_url($url, PHP_URL_QUERY);
        parse_str($urlQuery, $urlParams);
        if (isset($urlParams[$param])) {
            return Youzan::getGoodsUrl($urlParams[$param], 0, $host);
        } else {
            return false;
        }
    }

    /**
     * 获取link协议
     * @param $str
     * @return string
     */
    private static function getProtocol($str)
    {
        return isset($str['scheme']) ? $str['scheme'] . '://' : self::PROTOCOL;
    }

    /**
     * 生成预览链接
     * @param $itemId
     * @param $type
     * @param string $channel_jump_params
     * @param int $channel_shop_id
     * @return false|string
     */
    public static function formatLink($itemId, $type, $channel_jump_params = '', $channel_shop_id = 0)
    {
        switch ($type) {
            case self::URL_TYPE_XIAOMIYOUPIN:
                return "https://m.xiaomiyoupin.com/detail?gid=" . $itemId;
            case self::URL_TYPE_AMAZON:
                return "https://www.amazon.cn/dp/" . $channel_jump_params;
            case self::URL_TYPE_XIAOEPINPIN:
                $jump = $channel_jump_params ? json_decode($channel_jump_params, true) : [];
                return $jump['DetailUrl'] ?? '';
            case self::URL_TYPE_TAOBAO :
                return self::PROTOCOL . 'item.taobao.com/item.htm?id=' . $itemId;
                break;
            case self::URL_TYPE_TMALL :
                return self::PROTOCOL . 'detail.tmall.com/item.htm?id=' . $itemId;
                break;
            case self::URL_TYPE_JD :
                return self::PROTOCOL . 'item.jd.com/' . $itemId . '.html';
                break;
            case self::URL_TYPE_YOUZAN:
                if ($channel_jump_params && $channel_shop_id) {
                    return Youzan::getGoodsUrl($channel_jump_params, $channel_shop_id);
                }
            case self::URL_TYPE_SAMSUNGESHOP:
                if ($channel_jump_params) {
                    return self::PROTOCOL . 'www.samsungeshop.com.cn/product/' . $channel_jump_params;
                }
                break;
        }
        return false;
    }

    public static function getShopUrl($channelType, $shopId, $sellerId)
    {
        $url = '';
        switch ($channelType) {
            case self::URL_TYPE_TAOBAO:
            case self::URL_TYPE_TMALL:
                $url = self::getTaoBaoShopUrl($shopId, $sellerId);
                break;
            case self::URL_TYPE_JD:
                $url = self::getJDShopUrl($shopId);
                break;
        }
        return $url;
    }

    /**
     * 获取淘宝店铺url
     * @param $shopId
     * @param string $sellerId
     * @return string
     */
    public static function getTaoBaoShopUrl($shopId, $sellerId = '')
    {
        $shopUrl = '';
        if (!empty($shopId)) {
            $shopUrl = self::PROTOCOL . 'shop' . $shopId . '.taobao.com';
        } else if (!empty($sellerId)) {
            $shopUrl = self::PROTOCOL . 'store.taobao.com/shop/view_shop.htm?user_number_id=' . $sellerId;
        }
        return $shopUrl;
    }

    public static function getJDShopUrl($shopId)
    {
        //'https://shop.m.jd.com/?shopId='.$shopId;
        return self::PROTOCOL . 'mall.jd.com/index-' . $shopId . '.html';
    }
}
